package ltg.ibutton.aquaroom.gui.tablet;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.GridLayout;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Observable;
import java.util.Observer;

import javax.swing.BoxLayout;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingConstants;

import ltg.ibutton.aquaroom.AquaRoomPersistence;
import ltg.ibutton.aquaroom.DyeTracer;
import ltg.ibutton.aquaroom.NoWaterException;
import ltg.ibutton.aquaroom.WaterSample;
import ltg.ibutton.core.Concept;
import ltg.ibutton.core.FactorySimulation;
import ltg.ibutton.core.Simulation;

public class TabletGui extends JFrame implements ActionListener, Observer {
	private static final long serialVersionUID = 1L;
	
	private static final int STATUS_NO_BUTTON = 0;
	private static final int STATUS_BUTTON_ATTACHED = 1;
	private static final int STATUS_BUTTON_REGISTERED = 2;

	private int xblocks, yblocks;
	private boolean phaseTwo = false;
	
	private JLabel top = null;
	
	private Hashtable<Point, Integer> coloredCells = null;
	private Hashtable<String, ImageIcon> imagemap = null;
	private ArrayList<Concept> attachedButtons = null;
	private ArrayList<String> ib = null;
	private ArrayList<JGridButton> buttons = null;
	private ArrayList<JLabel> numlabels = null;
	private ArrayList<JLabel> alphalabels = null;
	private JGridButton confirm = null;
	
	private JGridButton clickedbutton = null;
	private Concept c = null;
	private String iconindex = ""; //necessary for displaying the dye/sample icon appropriately on the top part
	private int appstatus = 0; //to distinguish from no button, button attached and button registered
	
	public TabletGui() {
		super();
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		this.setUndecorated(true);

        GraphicsDevice gd = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
        //gd.setFullScreenWindow(this);
        int screenwidth = gd.getDisplayMode().getWidth();
        int screenheight = gd.getDisplayMode().getHeight();
		
		imagemap = new Hashtable<String, ImageIcon>();
        imagemap.put("blue", new ImageIcon("img/tube_blue.png"));
		imagemap.put("green", new ImageIcon("img/tube_green.png"));
		imagemap.put("yellow", new ImageIcon("img/tube_yellow.png"));
		imagemap.put("orange", new ImageIcon("img/tube_orange.png"));
		imagemap.put("red", new ImageIcon("img/tube_red.png"));
	    imagemap.put("sample", new ImageIcon("img/tube_empty.png"));
	    imagemap.put("null", new ImageIcon("img/null.png"));
	    imagemap.put("rock", new ImageIcon("img/rocks.png"));
	    imagemap.put("bluedye", new ImageIcon("img/bluedrop.png"));
	    imagemap.put("greendye", new ImageIcon("img/greendrop.png"));
	    imagemap.put("orangedye", new ImageIcon("img/orangedrop.png"));
	    imagemap.put("reddye", new ImageIcon("img/reddrop.png"));
	    imagemap.put("yellowdye", new ImageIcon("img/yellowdrop.png"));
	    imagemap.put("clearwater", new ImageIcon("img/waterdrop.png"));
		
		attachedButtons = new ArrayList<Concept>();
		buttons = new ArrayList<JGridButton>();
		numlabels = new ArrayList<JLabel>();
		alphalabels = new ArrayList<JLabel>();
		coloredCells = AquaRoomPersistence.getColoredTiles();
		
		phaseTwo = AquaRoomPersistence.phaseTwo();
		
		Hashtable<String, Float> classroomconf = AquaRoomPersistence.getClassroomConf();
		xblocks = classroomconf.get("xblocks").intValue();
		yblocks = classroomconf.get("yblocks").intValue();
		System.out.println(xblocks + " " + yblocks);
		
			top = new JLabel(imagemap.get("null"), SwingConstants.CENTER);
			top.setMinimumSize(new Dimension(1024, 80));
			Font f = new Font("Dialog", Font.PLAIN, 24);
			top.setFont(f);
			JPanel toppane = new JPanel(new BorderLayout());
			//toppane.setBackground(new Color(255, 0, 0));
			//toppane.setMinimumSize(new Dimension(1024, 600));
			toppane.setMaximumSize(new Dimension(1024, 100));
			toppane.add(top, BorderLayout.CENTER);
			confirm = new JGridButton("Confirm"); 
			confirm.addActionListener(this);
			confirm.setEnabled(false);
			toppane.add(confirm, BorderLayout.LINE_END);
			
			JPanel alphalabelspanel = new JPanel(new GridLayout(1, xblocks));	
			for(int j=0; j<xblocks; j++) {
				JLabel lbl = new JLabel(String.valueOf((char) (j + (int) 'A')), SwingConstants.CENTER);
				alphalabels.add(lbl);
	    		alphalabelspanel.add(lbl);
	    	}
			
			JPanel numlabelspanel = new JPanel(new GridLayout(yblocks, 1));
	        for(int i=0; i < yblocks; i++) {
	        	JLabel lbl = new JLabel((i+1) + "   ", SwingConstants.TRAILING);
	        	numlabels.add(lbl);
	        	numlabelspanel.add(lbl);
	        }
			
			JPanel pane = new JPanel(new GridLayout(yblocks, xblocks)); // Grid initialization
	        for(int i=0; i<yblocks; i++) {
	        	for(int j=0; j<xblocks; j++) {
	        		JGridButton btn = new JGridButton();
	        		btn.setCoords(j, i);
	        		Integer cc = coloredCells.get(new Point(j, i)); // button initialization according to the info stored in the config coloredtiles.conf file
	        		if(cc != null) {
	        			switch(cc) {
		        			case 0: btn.setText(""); btn.setIcon(imagemap.get("null")); break;
							case 1: btn.setText(""); btn.setIcon(imagemap.get("rock")); break;
							case 2: btn.setText(""); btn.setIcon(imagemap.get("clearwater")); break;
							case 3: btn.setText(""); btn.setIcon(imagemap.get(AquaRoomPersistence.getTilesColor() + "dye")); break;
							case 4: btn.setText(""); btn.setIcon(imagemap.get("sample")); break;
							case 5: btn.setText(""); btn.setIcon(imagemap.get(AquaRoomPersistence.getTilesColor()));
	        			}
	        			btn.setStatus(cc);
	        		}
	        		btn.addActionListener(this);
	        		btn.setFocusPainted(false);
	        		
	        		btn.addMouseListener(new MouseAdapter() { // label highlighting
	                    public void mouseEntered(MouseEvent e) {
	                    	JGridButton b = (JGridButton) e.getSource();
	                    	numlabels.get(b.getCoordY()).setOpaque(true);
	                    	numlabels.get(b.getCoordY()).setBackground(new Color(255,255,150));
	                    	alphalabels.get(b.getCoordX()).setOpaque(true);
	                    	alphalabels.get(b.getCoordX()).setBackground(new Color(255,255,150));
	                    }
	                    public void mouseExited(MouseEvent e) { // label de-highligthing
	                    	JGridButton b = (JGridButton) e.getSource();
	                    	numlabels.get(b.getCoordY()).setOpaque(false);
	                    	alphalabels.get(b.getCoordX()).setOpaque(false);
	                    	numlabels.get(b.getCoordY()).setBackground(Color.LIGHT_GRAY);
	                    	alphalabels.get(b.getCoordX()).setBackground(Color.LIGHT_GRAY);
	                    }
	                });
	        		
	        		buttons.add(btn);
	        		pane.add(btn);
	        	}
	        }
	        
	        JPanel maintop = new JPanel (new BorderLayout());
	        maintop.add(new JLabel("       "), BorderLayout.WEST);
	        maintop.add(alphalabelspanel, BorderLayout.CENTER);
	        
	        JPanel main = new JPanel(new BorderLayout());
	        
	        main.add(maintop, BorderLayout.NORTH);
	        main.add(numlabelspanel, BorderLayout.WEST);
	        main.add(pane, BorderLayout.CENTER);
        
        this.getContentPane().setLayout(new BoxLayout(this.getContentPane(), BoxLayout.PAGE_AXIS));
        this.getContentPane().add(toppane);
        this.getContentPane().add(main);
        
        this.setSize(screenwidth,screenheight);
        //this.setSize(1024,768);
        this.setVisible(true);
        
        //Model
        Simulation sim = FactorySimulation.getSim();
        sim.addObserver(this);
	}

	@Override
	public void actionPerformed(ActionEvent e) {
		JGridButton btn = (JGridButton) e.getSource();
		int x = btn.getCoordX();
		int y = btn.getCoordY();
		if(btn != confirm) { // click from a grid button
			clickedbutton = btn;
			switch(appstatus) {
				case STATUS_BUTTON_ATTACHED: // tube just inserted
					appstatus = STATUS_BUTTON_REGISTERED;
					System.out.println(btn.getCoords()[0] + " " + btn.getCoords()[1]);
					btn.setIcon(imagemap.get(iconindex));
					top.setIcon(imagemap.get("null"));
					for(Iterator<JGridButton> i = buttons.iterator(); i.hasNext();) {
						JGridButton tmpbtn = i.next();
						if(tmpbtn != btn)
							tmpbtn.setEnabled(false);
					}
					
					if(c.getClass().getName().equals("ltg.ibutton.aquaroom.WaterSample")) {
						btn.setStatus(4);
			    		((WaterSample) c).setX(x);
			    		((WaterSample) c).setY(y);
			    	}
			    	else { // dye injection
			    		btn.setStatus(5);
			    		((DyeTracer) c).setX(x);
			    		((DyeTracer) c).setY(y);
			    		((DyeTracer) c).setStationId(AquaRoomPersistence.getThisStationId());
			    		int n = JOptionPane.showConfirmDialog(
			    			    this,
			    			    "You are injecting a new dye. This will initiate a new session and clear the map. Do you want to continue?",
			    			    "Are you sure?",
			    			    JOptionPane.YES_NO_OPTION);
			    		if(n != JOptionPane.YES_OPTION)
			    			break;
			    		
			    		for(Iterator<JGridButton> i = buttons.iterator(); i.hasNext();) {
			    			JGridButton tmpbtn = i.next();
			    			if(tmpbtn != btn) {
			    				tmpbtn.setIcon(imagemap.get("null"));
			    				tmpbtn.setStatus(0); // wiping out the all map
			    			}
			    		}
					}
										
					confirm.setEnabled(true);
					break;
					
				case STATUS_BUTTON_REGISTERED: // tube inserted and position chosen by clicking on one button
					appstatus = STATUS_BUTTON_ATTACHED;
					
					Integer cc = coloredCells.get(new Point(btn.getCoordX(), btn.getCoordY()));
		        	btn.setEnabled(true);
		        	if(cc != null) {
		        		switch(cc) {
		        			case 0: btn.setText(""); btn.setIcon(imagemap.get("null")); break;
		        			case 1: btn.setText(""); btn.setIcon(imagemap.get("rock")); break;
		        			case 2: btn.setText(""); btn.setIcon(imagemap.get("clearwater")); break;
		        			case 3: btn.setText(""); btn.setIcon(imagemap.get(AquaRoomPersistence.getTilesColor() + "dye")); break;
		        			case 4: btn.setText(""); btn.setIcon(imagemap.get("sample")); break;
		        			case 5: btn.setText(""); btn.setIcon(imagemap.get(AquaRoomPersistence.getTilesColor()));
		        		}
		        	}
		        	else {
		        		btn.setText("");
		        		btn.setIcon(imagemap.get("null"));
		        	}
					
					top.setIcon(imagemap.get(iconindex));
					for(Iterator<JGridButton> i = buttons.iterator(); i.hasNext();) {
						JGridButton tmpbtn = i.next();
						if(tmpbtn != btn)
							tmpbtn.setEnabled(true);
					}
					
					confirm.setEnabled(false);
					break;
					
				default: // no buttons attached
					Concept c = AquaRoomPersistence.getConceptFromCoords(btn.getCoordX(), btn.getCoordY());
					int current = btn.getStatus();
					int next = 1;
					if(current < 3)						
						next = (btn.getStatus()+1)%4;
					if(current == 3)
						next = 0;
					btn.setStatus(next);
					switch(next) {
						case 0: 
							btn.setText(""); 
							if(c != null) {
								if(c.getClass().getName().equals("ltg.ibutton.aquaroom.DyeTracer")) {								
									btn.setIcon(imagemap.get(AquaRoomPersistence.getTilesColor()));
									btn.setStatus(5);
								}
								else {
									btn.setIcon(imagemap.get("sample")); 
									btn.setStatus(4);
								}
							}
							else {
								btn.setIcon(imagemap.get("null"));
								btn.setStatus(0);
							}
							break;
						case 1: btn.setText(""); btn.setIcon(imagemap.get("rock")); break;
						case 2: btn.setText(""); btn.setIcon(imagemap.get("clearwater")); break;
						case 3: btn.setText(""); btn.setIcon(imagemap.get(AquaRoomPersistence.getTilesColor()+ "dye"));
					}
					AquaRoomPersistence.setColoredTiles(buttons); // stores the info when there's no button attached
			}
		}
		else { // click from the confirm button
			clickedbutton = null;
	        System.err.println(c);
	        confirm.setEnabled(false);
			try {
				AquaRoomPersistence.storeConcept(c);
				if(!phaseTwo) {
					JOptionPane.showMessageDialog(this,
						    "You found water!!!",
						    "CONGRATULATIONS!!!",
						    JOptionPane.INFORMATION_MESSAGE);
				}
				AquaRoomPersistence.setColoredTiles(buttons); // saving the new map (wiped out only if a dye has been just injected)
				//if(c.getClass().getName().equals("ltg.ibutton.aquaroom.DyeTracer"))
					//AquaRoomPersistence.clearSession(); // de-activate all the operations made during the last session
			} catch (NoWaterException e1) {
				JOptionPane.showMessageDialog(this,
					    "You hit a rock!!!",
					    "NO WATER!!!",
					    JOptionPane.WARNING_MESSAGE);
			}
			for(Iterator<JGridButton> i = buttons.iterator(); i.hasNext();) {
				JGridButton tmpbtn = i.next();
				if(tmpbtn != btn)
					tmpbtn.setEnabled(true);
			}
		}
	}

	@Override
	public void update(Observable arg0, Object arg1) {
		ImageIcon icon = imagemap.get("null");
		String scaffolding = null;
		System.out.println("update triggered");
		
		ib = (ArrayList<String>) arg1; //list of current attached buttons
		
		if((ib.isEmpty() || ib.size() != attachedButtons.size()) && appstatus != STATUS_BUTTON_REGISTERED) {
			coloredCells = AquaRoomPersistence.getColoredTiles();
			attachedButtons.clear();
			for(Iterator<JGridButton> i = buttons.iterator(); i.hasNext();) {
				JGridButton tmpbtn = i.next();
	        	Integer cc = coloredCells.get(new Point(tmpbtn.getCoordX(), tmpbtn.getCoordY()));
	        	tmpbtn.setEnabled(true);
	        	if(cc != null) {
	        		switch(cc) {
	        			case 0: tmpbtn.setText(""); tmpbtn.setIcon(imagemap.get("null")); break;
	        			case 1: tmpbtn.setText(""); tmpbtn.setIcon(imagemap.get("rock")); break;
	        			case 2: tmpbtn.setText(""); tmpbtn.setIcon(imagemap.get("clearwater")); break;
	        			case 3: tmpbtn.setText(""); tmpbtn.setIcon(imagemap.get(AquaRoomPersistence.getTilesColor() + "dye")); break;
	        			case 4: tmpbtn.setText(""); tmpbtn.setIcon(imagemap.get("sample")); break;
	        			case 5: tmpbtn.setText(""); tmpbtn.setIcon(imagemap.get(AquaRoomPersistence.getTilesColor()));
	        		}
	        	}
	        	else {
	        		tmpbtn.setText("");
	        		tmpbtn.setIcon(imagemap.get("null"));
	        	}
			}
		}
		
		if(!ib.isEmpty()) {		
			appstatus = STATUS_BUTTON_ATTACHED;
			for(Iterator<JGridButton> i = buttons.iterator(); i.hasNext();) {
				JGridButton tmpbtn = i.next();
				tmpbtn.setEnabled(true);
			}
			confirm.setEnabled(false);
			
			if(clickedbutton != null) {
				Integer cc = coloredCells.get(new Point(clickedbutton.getCoordX(), clickedbutton.getCoordY()));
	        	if(cc != null) {
	        		switch(cc) {
	        			case 0: clickedbutton.setText(""); clickedbutton.setIcon(imagemap.get("null")); break;
	        			case 1: clickedbutton.setText(""); clickedbutton.setIcon(imagemap.get("rock")); break;
	        			case 2: clickedbutton.setText(""); clickedbutton.setIcon(imagemap.get("clearwater")); break;
	        			case 3: clickedbutton.setText(""); clickedbutton.setIcon(imagemap.get(AquaRoomPersistence.getTilesColor() + "dye")); break;
	        			case 4: clickedbutton.setText(""); clickedbutton.setIcon(imagemap.get("sample")); break;
	        			case 5: clickedbutton.setText(""); clickedbutton.setIcon(imagemap.get(AquaRoomPersistence.getTilesColor()));
	        		}
	        	}
	        	else {
	        		clickedbutton.setText("");
	        		clickedbutton.setIcon(imagemap.get("null"));
	        	}
			}
		}
		else {
			appstatus = STATUS_NO_BUTTON;
		}
		
		for(Iterator<String> j = ib.iterator(); j.hasNext();) {
			String bid = (String) j.next();
			c = AquaRoomPersistence.getConceptFromBid(bid);
			if(c.getClass().getName().equals("ltg.ibutton.aquaroom.DyeTracer")) {
				attachedButtons.add((DyeTracer) c);
				icon = imagemap.get(((DyeTracer) c).getColor());
	    		scaffolding = "  A tube containing a "+((DyeTracer) c).getColor()+" dye tracer has been detected.";
	    		iconindex = ((DyeTracer) c).getColor();
			}
			else {
				attachedButtons.add((WaterSample) c);
				icon = imagemap.get("sample");
				scaffolding = "  A test tube has been detected.";
				iconindex = "sample";
			}
			
		}	
		top.setText(scaffolding);
    	top.setIcon(icon);	
	}	
}
